home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / program / misc / fpl-v13.lha / fpl / src / memory.c < prev    next >
C/C++ Source or Header  |  1995-06-28  |  19KB  |  684 lines

  1. /******************************************************************************
  2.  *                   FREXX PROGRAMMING LANGUAGE                  *
  3.  ******************************************************************************
  4.  
  5.  memory.c
  6.  
  7.  Memory functions handling all allocating and freeing.
  8.  
  9.  *****************************************************************************/
  10.  
  11. /************************************************************************
  12.  *                                                                      *
  13.  * fpl.library - A shared library interpreting script langauge.         *
  14.  * Copyright (C) 1992-1994 FrexxWare                                    *
  15.  * Author: Daniel Stenberg                                              *
  16.  *                                                                      *
  17.  * This program is free software; you may redistribute for non          *
  18.  * commercial purposes only. Commercial programs must have a written    *
  19.  * permission from the author to use FPL. FPL is *NOT* public domain!   *
  20.  * Any provided source code is only for reference and for assurance     *
  21.  * that users should be able to compile FPL on any operating system     *
  22.  * he/she wants to use it in!                                           *
  23.  *                                                                      *
  24.  * You may not change, resource, patch files or in any way reverse      *
  25.  * engineer anything in the FPL package.                                *
  26.  *                                                                      *
  27.  * This program is distributed in the hope that it will be useful,      *
  28.  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
  29.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                 *
  30.  *                                                                      *
  31.  * Daniel Stenberg                                                      *
  32.  * Ankdammsgatan 36, 4tr                                                *
  33.  * S-171 43 Solna                                                       *
  34.  * Sweden                                                               *
  35.  *                                                                      *
  36.  * FidoNet 2:201/328    email:dast@sth.frontec.se                       *
  37.  *                                                                      *
  38.  ************************************************************************/
  39.  
  40. #ifdef UNIX
  41. #include <sys/types.h>
  42. #elif defined(AMIGA)
  43. #include <exec/types.h>
  44. #include <exec/memory.h>
  45. #include <proto/exec.h>
  46. #endif
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <stddef.h>
  51. #include "script.h"
  52. #include "memory.h"
  53. #include "debug.h"
  54.  
  55. static void  REGARGS LinkMemory(struct Data *, struct MemInfo *, uchar);
  56. static void  REGARGS UnLinkMemory(struct Data *, struct MemInfo *, uchar);
  57.  
  58. #ifdef DEBUG
  59. extern long mem;
  60. extern long maxmem;
  61. long malloc_count=0;
  62. long Mmalloc_count=0;
  63. long free_mem=0;
  64. long max_free_mem=0;
  65. #endif
  66.  
  67. /**********************************************************************
  68.  *
  69.  * MallocCycle();
  70.  *
  71.  * Get memory to a MALLOC_DYNAMIC alloc. The memory can be taken from the
  72.  * memory cache if any is available.
  73.  *
  74.  ******/
  75.  
  76. void  *MallocCycle(struct Data *scr, long size
  77. #ifdef DEBUGPARAMETERS2
  78. DEBUGPARAMETERS2
  79. #endif
  80. )
  81. {
  82. #if MEMORY_QUEUE>0
  83.   if(size<256) {
  84.     register struct FreeBlock *pnt;
  85.     size>>=4;
  86.     if(pnt=scr->blox[size]) {
  87.       scr->blox[size]=pnt->next;
  88.       scr->blockcount[size]--;
  89. #ifdef DEBUGPARAMETERS2
  90.       pnt->mem.line=line;
  91.       pnt->mem.source=source; /* the two debugparameters */
  92. #endif
  93. #ifdef DEBUG
  94.       Mmalloc_count++;
  95.       free_mem-=(((struct MemInfo *)pnt)->size&SIZEBITS)+
  96.     sizeof(struct MemInfo);
  97.       CheckMem(scr, (uchar *)pnt+sizeof(struct MemInfo));
  98. #endif
  99.       return (void *)((uchar *)pnt+sizeof(struct MemInfo));
  100.     } else
  101.       size=(size<<4)+15;
  102.   }
  103. #endif
  104.  
  105. #ifdef DEBUGPARAMETERS2
  106.   return Malloc(scr, size, MALLOC_DYNAMIC, source, line);
  107. #else
  108.   return Malloc(scr, size, MALLOC_DYNAMIC);
  109. #endif
  110. }
  111.  
  112. /**********************************************************************
  113.  *
  114.  * DefaultAlloc();
  115.  *
  116.  * THis function allocates memory from the system. Replaceable with the
  117.  * tag FPLTAG_INTERNAL_ALLOC.
  118.  *
  119.  ******/
  120.  
  121. void ASM *DefaultAlloc(DREG(0) long size, AREG(0) void *userdata)
  122. {
  123. #ifdef AMIGA
  124.   return (void *)AllocMem(size, MEMF_ANY);
  125. #elif defined(UNIX)
  126.   return (void *)malloc(size);
  127. #endif
  128. }
  129.  
  130. /**********************************************************************
  131.  *
  132.  * DefaultDealloc();
  133.  *
  134.  * This functions does nothing but returns allocated memory to the system.
  135.  * It can be replaced by a user function specified with the tag
  136.  * FPLTAG_INTERNAL_DEALLOC.
  137.  *
  138.  ******/
  139.  
  140. void ASM DefaultDealloc(AREG(1) void *point,
  141.                         DREG(0) long size,
  142.                         AREG(0) void *userdata)
  143. {
  144. #ifdef AMIGA  
  145.   FreeMem(point, size);
  146. #elif UNIX
  147.   free(point);
  148. #endif
  149. }
  150.  
  151. /**********************************************************************
  152.  *
  153.  * Malloc();
  154.  *
  155.  * Allocate memory for real.
  156.  *
  157.  ******/
  158.  
  159. void ASM *Malloc(AREG(0) struct Data *scr, DREG(0) long size, DREG(1) uchar type
  160. #ifdef DEBUGPARAMETERS1
  161. DEBUGPARAMETERS1
  162. #endif
  163. )
  164. {
  165.   uchar *alloc;
  166.  
  167. #ifdef DEBUG
  168.   struct MemInfo *meminfo;
  169.  
  170.   size+=MEMORY_COOKIE; /* add extra bytes after the block! */
  171. #endif
  172.  
  173.   alloc=(uchar *)scr->Alloc(size+sizeof(struct MemInfo), scr->userdata);
  174.  
  175.   if(!alloc) {
  176.     /* If the first alloc failed, flush caches and retry! */
  177.     FlushFree(scr);
  178.     alloc=(uchar *)scr->Alloc(size+sizeof(struct MemInfo),
  179.                              scr->userdata);
  180.     if(!alloc)
  181.       return(NULL);
  182.   }
  183.  
  184.   ((struct MemInfo *)alloc)->size=size | (type * ALLOCBIT);
  185.   /* size = size | (type * 1<<31) */
  186.  
  187.   LinkMemory(scr, (struct MemInfo *)alloc, type);
  188.  
  189. #ifdef DEBUGPARAMETERS2
  190.   meminfo=(struct MemInfo *)alloc;
  191.  
  192.   meminfo->line=line;
  193.   meminfo->source=source; /* the two debugparameters */
  194. #endif
  195.  
  196. #ifdef DEBUG
  197. #if PRE_COOKIE>0
  198.   /* Fill the pre_cookie with junk too! */
  199.   memset((void *)meminfo->dummy, 0xbb,
  200.      sizeof(struct MemInfo)-offsetof(struct MemInfo, dummy));
  201. #endif
  202.  
  203. #if MEMORY_COOKIE>0
  204.   memset((uchar *)meminfo + sizeof(struct MemInfo) + size-MEMORY_COOKIE,
  205.      0xbb, MEMORY_COOKIE);
  206. #endif
  207.  
  208.   Mmalloc_count++;
  209.   malloc_count++;
  210.   mem+=size+sizeof(struct MemInfo);
  211.   if(mem>maxmem)
  212.     maxmem=mem;
  213. #endif
  214.   return (void *) ((uchar *)alloc+sizeof(struct MemInfo));
  215. }
  216.  
  217. /**********************************************************************
  218.  *
  219.  * LinkMemory();
  220.  *
  221.  * Adds the specifed memory area to the certain memory type list.
  222.  *
  223.  *****/
  224.  
  225. static void REGARGS
  226. LinkMemory(struct Data *scr,
  227.            struct MemInfo *point,
  228.            uchar type)
  229. {
  230.   point->prev=scr->MallocKey[type];     /* previous */
  231.   point->next=NULL;         /* next */
  232.   if(scr->MallocKey[type])
  233.     point->prev->next=point;
  234.   scr->MallocKey[type] = (void *)point;
  235. }
  236.  
  237.  
  238. /**********************************************************************
  239.  *
  240.  * UnLinkMemory();
  241.  *
  242.  * Deletes the specifed memory area from the certain memory type list.
  243.  *
  244.  *****/
  245.  
  246. static void REGARGS
  247. UnLinkMemory(struct Data *scr,
  248.              struct MemInfo *point,
  249.              uchar type)
  250. {
  251.   if(scr->MallocKey[type]==point) {
  252.     /* if this is the last Malloc, set `last' to `prev' */
  253.     scr->MallocKey[type]=point->prev;
  254.     if(scr->MallocKey[type])
  255.       scr->MallocKey[type]->next=NULL;
  256.   } else {
  257.     /* point the previous' `next' to our `next', and our next `previous'
  258.        to our `previous'. Unlink us from the chain */
  259.     if(point->prev)
  260.       /* only if we aren't the _first_ Malloc() ! */
  261.       point->prev->next=point->next;
  262.     if(point->next)
  263.       /* only if there is a next! */
  264.       point->next->prev=point->prev;
  265.   }
  266. }
  267.  
  268.  
  269. /**********************************************************************
  270.  *
  271.  * FreeCycle();
  272.  *
  273.  * Free the MALLOC_DYNAMIC allocated memory to the memory cache, or if
  274.  * that is full, free for real.
  275.  *
  276.  * In this routine we do not have to bitwise and SIZEBITS since the ALLOCBIT
  277.  * is never set when this is called!
  278.  *
  279.  ******/
  280.  
  281. void  REGARGS FreeCycle(struct Data *scr, void *ptr)
  282. {
  283.   struct MemInfo *point=(struct MemInfo *)((uchar *)ptr-sizeof(struct MemInfo));
  284.   /* `point' points to the MemInfo structure */
  285. #if defined(DEBUG) && defined(UNIX)
  286.   if(point->size&ALLOCBIT) {
  287.     fprintf(stderr, "*WARNING* Illegal free() of %d bytes!\n",
  288.         point->size&SIZEBITS);
  289.   }
  290. #endif
  291.  
  292. #ifdef DEBUG
  293.   CheckMem(scr, ptr);
  294. #endif
  295.  
  296. #if MEMORY_QUEUE>0
  297.   if(point->size<256+MEMORY_COOKIE) {
  298.     register long size=point->size-MEMORY_COOKIE>>4;
  299.     if(scr->blockcount[size]<MEMORY_QUEUE_SIZE) {
  300. #ifdef DEBUG
  301.       memset(ptr, 0xaa, point->size-MEMORY_COOKIE);
  302.  
  303.       free_mem+=point->size+sizeof(struct MemInfo);
  304.       if(free_mem>max_free_mem)
  305.     max_free_mem=free_mem;
  306. #endif
  307.       ((struct FreeBlock *)point)->next=scr->blox[size];
  308.       scr->blox[size]=(struct FreeBlock *)point;
  309.       scr->blockcount[size]++;
  310.       return;
  311.     }
  312.   }
  313. #endif
  314.   Free(scr, ptr, MALLOC_DYNAMIC);
  315. }
  316.  
  317. /**********************************************************************
  318.  *
  319.  * Free();
  320.  *
  321.  * Free a allocated memory area of a certain type. The freed memory
  322.  * area gets freed `for real'.
  323.  *
  324.  *****/
  325.  
  326. void ASM Free(AREG(0) struct Data *scr, AREG(1) void *ptr, DREG(0) uchar type)
  327. {
  328.   struct MemInfo *point=(struct MemInfo *)((uchar *)ptr-sizeof(struct MemInfo));
  329.   /* `point' points to the MemInfo structure: */
  330. #ifdef DEBUG
  331.   CheckMem(scr, ptr);
  332. #endif
  333.   UnLinkMemory(scr, point, type);
  334. #ifdef DEBUG
  335.   mem-=(point->size&SIZEBITS)+sizeof(struct MemInfo);
  336. #endif
  337.   scr->Dealloc(point,
  338.                (point->size&SIZEBITS)+sizeof(struct MemInfo),
  339.                scr->userdata);
  340. }
  341.  
  342. #ifdef DEBUG
  343. /**********************************************************************
  344.  *
  345.  * CheckMem();
  346.  *
  347.  * Check a special malloc to see that it hasn't overwritten it's boundaries.
  348.  *
  349.  ******/
  350.  
  351. ReturnCode REGARGS CheckMem(struct Data *scr, void *ptr)
  352. {
  353.   long i;
  354.   long b, c;
  355.   uchar *data;
  356.   struct MemInfo *point;
  357.   /* `point' points to the MemInfo structure: */
  358.   point=(struct MemInfo *)((uchar *)ptr-sizeof(struct MemInfo));
  359.  
  360. #if MEMORY_COOKIE>0
  361.   for(i=b=0;i<MEMORY_COOKIE; i++) {
  362.     data=(uchar *)point+ sizeof(struct MemInfo)+i+(point->size&SIZEBITS)-MEMORY_COOKIE;
  363.     if(*data!= 0xbb)
  364.       b++;
  365.   }
  366.  
  367.   if(b) {
  368. #ifdef AMIGA
  369.     /* ERROR */
  370.     point=NULL;
  371. #else
  372.     fprintf(stderr, "Memory violation: malloc(%d) was abused %d bytes after block!\n",
  373.         (point->size&SIZEBITS), b);
  374. #endif
  375.   }
  376. #endif
  377.  
  378. #if PRE_COOKIE>0
  379.   for(c=i=0;i<sizeof(struct MemInfo)-offsetof(struct MemInfo, dummy); i++)
  380.     if(point->dummy[i]!= 0xbb)
  381.       c++;
  382.  
  383.   if(c) {
  384. #ifdef AMIGA
  385.     /* ERROR */
  386.     point=NULL;
  387. #else
  388.     fprintf(stderr, "Memory violation: malloc(%d) was abused %d bytes before block!\n",
  389.         (point->size&SIZEBITS), c);
  390. #endif
  391.   }
  392. #endif
  393.  
  394.   return(b+c?FPLERR_OUT_OF_MEMORY:FPL_OK);
  395. }
  396. #endif
  397.  
  398. /**********************************************************************
  399.  *
  400.  * FreeAll();
  401.  *
  402.  * Free all memory allocated with specified type!
  403.  *
  404.  ******/
  405.  
  406. void REGARGS
  407. FreeAll(struct Data *scr,
  408.         uchar type)
  409. {
  410.   struct MemInfo *point;
  411.   void *prev;
  412. #ifdef DEBUG
  413.   long size;
  414. #endif
  415.   if(!scr->MallocKey[type])
  416.     return;
  417.   do {
  418.     point=scr->MallocKey[type];
  419.     /* `point' points to the MemInfo structure! */
  420.  
  421.     prev=(void *)point->prev;
  422.  
  423. #ifdef DEBUG
  424.     mem-=(point->size&SIZEBITS)+sizeof(struct MemInfo);
  425.     size=(point->size&SIZEBITS);
  426.  
  427.     if(type == MALLOC_DYNAMIC)
  428.       free_mem=0; /* no free mem left in memory queuing */
  429. #endif
  430.     scr->Dealloc(scr->MallocKey[type],
  431.                  (point->size&SIZEBITS)+sizeof(struct MemInfo),
  432.                  scr->userdata);
  433.   } while(scr->MallocKey[type]=prev);
  434.   if(type==MALLOC_DYNAMIC)
  435.     InitFree(scr); /* init the memory cache tables to prevent accidents with
  436.               FPLSEND_FLUSHCACHE */
  437. }
  438.  
  439. /**********************************************************************
  440.  *
  441.  * InitFree()
  442.  *
  443.  * Initialize the memory cache/queue.
  444.  *
  445.  ******/
  446.  
  447. void REGARGS InitFree(struct Data *scr)
  448. {
  449.   memset(scr->blox, 0, sizeof(struct FreeBlock *)*BLOCK_ENTRIES);
  450.   memset(scr->blockcount, 0, sizeof(long)*BLOCK_ENTRIES);
  451. }
  452.  
  453. /**********************************************************************
  454.  *
  455.  * FlushFree();
  456.  *
  457.  * Flush the memory chache.
  458.  *
  459.  *******/
  460.  
  461. void REGARGS FlushFree(struct Data *scr)
  462. {
  463.   register long i;
  464.   for(i=0; i<BLOCK_ENTRIES;i++) {
  465.     register struct FreeBlock *pnt;
  466.     while(pnt=scr->blox[i]) {
  467.       scr->blox[i]=pnt->next; /* delete block from chain */
  468.       scr->blockcount[i]--;   /* count down counter */
  469.       /* free block for real */
  470.       Free(scr, (uchar *)pnt+sizeof(struct MemInfo), MALLOC_DYNAMIC);
  471.     }
  472.   }
  473. }
  474.  
  475. /**********************************************************************
  476.  *
  477.  * SwapMem();
  478.  *
  479.  * If type is MALLOC_STATIC or MALLOC_DYNAMIC, this function will secure that
  480.  * the memory area will be of that kind!
  481.  *
  482.  * THE AREA MUST BE ALLOCATED WHEN THIS CONVERTION HAPPENS!!! IT MUST NOT
  483.  * BE IN THE FREE MEMORY CACHE/QUEUE LIST.
  484.  *
  485.  * This function is mainly used when storing global data. Since all
  486.  * MALLOC_DYNAMIC data gets freed at the end of a FPL program run, we must
  487.  * convert the mallocs to be able to keep them for next execution!
  488.  *
  489.  *****/
  490.  
  491. void REGARGS SwapMem(struct Data *scr, void *ptr, uchar type)
  492. {
  493.   struct MemInfo *point;
  494.   if(ptr) {
  495.     /* points to something! */
  496.  
  497.     point=(struct MemInfo *)((uchar *)ptr-sizeof(struct MemInfo));
  498.     /* `point' points to the MemInfo structure: */
  499.     if(point->size&ALLOCBIT && type==MALLOC_DYNAMIC) {
  500.       /* This is a MALLOC_STATIC alloc */
  501.       UnLinkMemory(scr, point, MALLOC_STATIC); /* take away from static list */
  502.       point->size&=SIZEBITS;
  503.       LinkMemory(scr, point, MALLOC_DYNAMIC);  /* insert in dynamic list */
  504.     } else if(!(point->size&ALLOCBIT) && type==MALLOC_STATIC) {
  505.       /* This is a MALLOC_DYNAMIC alloc */
  506.       UnLinkMemory(scr, point, MALLOC_DYNAMIC); /* take away from dynamic list */
  507.       point->size|=ALLOCBIT;
  508.       LinkMemory(scr, point, MALLOC_STATIC);    /* insert in static list */
  509.     }
  510.     /* If no if() statement was reached, the memory area type was corect! */
  511.   }
  512. }
  513.  
  514. /**********************************************************************
  515.  *
  516.  * TypeMem()
  517.  *
  518.  * Returns the type of the specified memory pointer.
  519.  * Returns MALLOC_STATIC or MALLOC_DYNAMIC.
  520.  *
  521.  ******************************************/
  522.  
  523. uchar REGARGS TypeMem(void *ptr)
  524. {
  525.   struct MemInfo *point=(struct MemInfo *)((uchar *)ptr-sizeof(struct MemInfo));
  526.   /* `point' points to the MemInfo structure: */
  527.   if(point->size&ALLOCBIT)
  528.     return MALLOC_STATIC;
  529.   return MALLOC_DYNAMIC;
  530. }
  531.  
  532. /**********************************************************************
  533.  *
  534.  * fplAlloc()
  535.  *
  536.  * fplAlloc() allocates memory and assign it to the fpl internal list of
  537.  * used memory. If fplFree() is called, this memory area will be free'd if
  538.  * not earlier. Free this memory using fplDealloc().
  539.  *
  540.  ******/
  541.  
  542. void PREFIX *fplAlloc(AREG(0) struct Data *scr, DREG(0) long size)
  543. {
  544. #ifdef DEBUGMAIL
  545.   DebugMail(scr, MAIL_FUNCTION, 500, "fplAlloc");
  546. #endif
  547.   if(!scr)
  548.     return(NULL);
  549.   return MALLOCA(size);
  550. }
  551.  
  552. /**********************************************************************
  553.  *
  554.  * fplDealloc()
  555.  *
  556.  * This function frees memory previously allocated with fplAlloc();
  557.  *
  558.  *****/
  559.  
  560. void PREFIX fplDealloc(AREG(0) struct Data *scr, AREG(1) void *ptr)
  561. {
  562. #ifdef DEBUGMAIL
  563.   DebugMail(scr, MAIL_FUNCTION, 500, "fplDealloc");
  564. #endif
  565.   if(!scr)
  566.     return;
  567.   FREE_KIND(ptr);
  568. }
  569.  
  570. /**********************************************************************
  571.  *
  572.  * fplAlloca()
  573.  *
  574.  * fplAlloca() allocates memory and assign it to the fpl internal list of
  575.  * used memory. The memory will only exist while executing the current file or
  576.  * until next program has been executed. If fplFree() is called, this memory
  577.  * area will also be free'd. Free this memory using fplDealloca(). This function
  578.  * will use the FPL internal memory caching system.
  579.  *
  580.  ******/
  581.  
  582. void PREFIX *fplAlloca(AREG(0) struct Data *scr, DREG(0) long size)
  583. {
  584. #ifdef DEBUGMAIL
  585.   DebugMail(scr, MAIL_FUNCTION, 500, "fplAlloca");
  586. #endif
  587.   if(!scr)
  588.     return(NULL);
  589.   return MALLOC(size);
  590. }
  591.  
  592. /**********************************************************************
  593.  *
  594.  * fplDealloca()
  595.  *
  596.  * This function frees memory previously allocated with fplAlloca();
  597.  *
  598.  *****/
  599.  
  600. void PREFIX fplDealloca(AREG(0) struct Data *scr, AREG(1) void *ptr)
  601. {
  602.   fplDealloc(scr, ptr);
  603. }
  604.  
  605. /***************************************************************
  606.  *
  607.  * fplAllocString()
  608.  *
  609.  * Returns a pointer to a memory block of the requested size.
  610.  * The memory block is initialized as a string and can be used
  611.  * when returning strings to FPL with fplSend(), without having
  612.  * to allocate memory, make FPL have to allocate memory and copy
  613.  * all your data and then you free your memory again.
  614.  *  Now all you have to do is allocate a string at once and then
  615.  * tell FPL in fplSend() using the FPLSEND_DONTCOPY_STRING. The memory
  616.  * block will then be used as it is by FPL.
  617.  *
  618.  * If you want to free the memory, you do that with fplFreeString().
  619.  * You must not free memory sent to FPL!
  620.  *
  621.  ********/
  622.  
  623. void PREFIX *fplAllocString(AREG(0) struct Data *scr, DREG(0) long size)
  624. {
  625.   uchar *ptr;
  626. #ifdef DEBUGMAIL
  627.   DebugMail(scr, MAIL_FUNCTION, 500, "fplAllocString");
  628. #endif
  629.   /*
  630.    * Allocate the memory DYNAMIC and convert it to staic later so that the
  631.    * memory block gets aligned properly and then later can get converted to
  632.    * DYNAMIC kind again without any risking anything!
  633.    */
  634.   ptr = MALLOC(size + sizeof(struct fplStr)); 
  635.  
  636.   if(!ptr)
  637.     return NULL;
  638.   
  639.   /*
  640.    * Convert this to static, most strings allocated like this are likely to
  641.    * be used as "static" memory areas!
  642.    */
  643.   SwapMem(scr, ptr, MALLOC_STATIC);
  644.  
  645.   ((struct fplStr *)ptr)->alloc=size;
  646.   ((struct fplStr *)ptr)->len=size; /* set default to entire string */
  647.  
  648.   ptr+=offsetof(struct fplStr, string); /* make 'ptr' point to the string
  649.                        entry */
  650.   return ptr; /* return string must be freed with fplFreeString() */
  651. }
  652.  
  653. void PREFIX fplFreeString(AREG(0) struct Data *scr, AREG(1) void *ptr)
  654. {
  655.   uchar *point=ptr;
  656. #ifdef DEBUGMAIL
  657.   DebugMail(scr, MAIL_FUNCTION, 500, "fplFreeString");
  658. #endif
  659.   if(!point)
  660.     return;
  661.  
  662.   point-=offsetof(struct fplStr, string); /* go to beginning of allocation */
  663.  
  664.   FREEA(point); /* free the string! */
  665. }
  666.  
  667. /**********************************************************************
  668.  *
  669.  * FreeKind()
  670.  *
  671.  * Frees the memory area, of both dynamic and static kinds!
  672.  *
  673.  ****************/
  674.  
  675. void REGARGS FreeKind(struct Data *scr, void *memory)
  676. {
  677.   if(MALLOC_DYNAMIC == TypeMem(memory)) {
  678.     FREE(memory);
  679.   }
  680.   else {
  681.     FREEA(memory);
  682.   }
  683. }
  684.